﻿#region Using Declaration

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.Xml.Linq;

#endregion Using Declaration

namespace T4_Eind_programma
{
    public class FileIO
    {
        #region Variable Declaration

        private const string fileNameOEE = "OEE.xml";

        private const string fileNameOrder = "Order.xml";
        private const string fileNameRemovedMengbatches = "Mengbatch.xml";
        private const string fileNameOEETags = "outputtags.txt";
        private const string directory = "/Files/";
        private string location;

        #endregion Variable Declaration

        #region Properties

        public string FileNameOEE
        {
            get { return fileNameOEE; }
        }

        public string FileNameOrder
        {
            get { return fileNameOrder; }
        }

        public string FileNameRemovedMengbatches
        {
            get { return fileNameRemovedMengbatches; }
        }

        public string Location
        {
            get { return location; }
        }

        #endregion Properties

        #region Constructor

        public FileIO()
        {
            location = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName + directory;
        }

        #endregion Constructor

        #region Checks

        public bool CheckStringForWrite(ItemInfo item)
        {
            bool write = false;
            StreamReader reader = new StreamReader(location + fileNameOEETags);
            List<string> tagsFromFile = new List<string>();
            while (!reader.EndOfStream)
            {
                tagsFromFile.Add(reader.ReadLine());
            }
            foreach (string stringFromFile in tagsFromFile)
            {
                if (stringFromFile == item.FilteredName) { write = true; }
            }
            return write;
        }

        #endregion Checks

        #region Read

        public BindingList<Order> ReadOrderList(string folderName, string fileName)
        {
            // deze kan zowel Historie als Orders uitlezen aangezien beide documenten hetzelfde opgebouwd zijn en beide opgebouwd zijn uit orders.
            BindingList<Order> orderList = new BindingList<Order>();
            if (File.Exists(folderName + fileName))
            {
                if (new FileInfo(location + fileNameOrder).Length < 3)
                {
                    File.Delete(location + fileNameOrder);
                }
                XmlReader reader = XmlReader.Create(folderName + fileName);
                XDocument x = XDocument.Load(reader);
                // laat alleen elementen zien waar de naam Order is

                var orderTables = x.Descendants("Order");

                foreach (var order in orderTables)
                {
                    orderList.Add(new Order(
                        Convert.ToInt32(order.Attribute("Nummer").Value), order.Attribute("Naam").Value, Convert.ToBoolean(order.Attribute("Klaar").Value)));

                    var mengbatchTables = order.Descendants("Mengbatch");

                    foreach (var mengbatch in mengbatchTables)
                    {
                        orderList[orderList.Count - 1].MengbatchList.Add(new Mengbatch(
                                   Convert.ToInt32(mengbatch.Attribute("Nummer").Value),
                                   mengbatch.Attribute("Productcode").Value, new Smaak(
                                   mengbatch.Attribute("Smaak").Value),
                                   Convert.ToInt32(mengbatch.Attribute("HoeveelheidVaten").Value),
                                   Convert.ToInt32(mengbatch.Attribute("Siroop").Value),
                                   Convert.ToInt32(mengbatch.Attribute("Mengtijd").Value),
                                   Convert.ToBoolean(mengbatch.Attribute("Verwarmen").Value),
                                   Convert.ToBoolean(mengbatch.Attribute("Handmatig").Value), new Doeltank(
                                   Convert.ToInt32(mengbatch.Attribute("Doeltank").Value)),
                                   Convert.ToBoolean(mengbatch.Attribute("Klaar").Value),
                        Convert.ToInt32(mengbatch.Attribute("VerwarmTijd").Value)));

                        var vulbatchTables = mengbatch.Descendants("Vulbatch");
                        foreach (var vulbatch in vulbatchTables)
                        {
                            orderList[orderList.Count - 1].MengbatchList[orderList[orderList.Count - 1].MengbatchList.Count - 1].VulbatchList.Add(new Vulbatch(
                                   Convert.ToInt32(vulbatch.Attribute("Nummer").Value),
                                   Convert.ToInt32(vulbatch.Attribute("Mengbatch").Value),
                                   Convert.ToInt32(vulbatch.Attribute("Aantalvaten").Value),
                                   Convert.ToBoolean(vulbatch.Attribute("Klaar").Value)));
                            string apparaten = vulbatch.Attribute("Klaar").Value;
                            string[] splitter = apparaten.Split(' ');
                            for (int z = 0; z < splitter.Length - 1; z++)
                            {
                                orderList[orderList.Count - 1].MengbatchList[orderList[orderList.Count - 1].MengbatchList.Count - 1].VulbatchList[z].GebruikteApparaten.Add(splitter[z]);
                            }
                        }
                    }
                }

                reader.Close();
            }
            return orderList;
        }

        private List<Mengbatch> ReadRemovedMengbatch(string folderName, string fileName, Order order, List<Mengbatch> mengbatchListFromFile)
        {
            if (File.Exists(folderName + fileName))
            {
                XmlReader reader = XmlReader.Create(folderName + fileName);
                XDocument x = XDocument.Load(reader);
                // laat alleen elementen zien waar de naam Mengbatch is
                var mengbatchTables = x.Descendants("Mengbatch");

                foreach (var mengbatch in mengbatchTables)
                {
                    mengbatchListFromFile.Add(new Mengbatch(
                               Convert.ToInt32(mengbatch.Attribute("Nummer").Value),
                               mengbatch.Attribute("Productcode").Value, new Smaak(
                               mengbatch.Attribute("Smaak").Value),
                               Convert.ToInt32(mengbatch.Attribute("HoeveelheidVaten").Value),
                               Convert.ToInt32(mengbatch.Attribute("Siroop").Value),
                               Convert.ToInt32(mengbatch.Attribute("Mengtijd").Value),
                               Convert.ToBoolean(mengbatch.Attribute("Verwarmen").Value),
                               Convert.ToBoolean(mengbatch.Attribute("Handmatig").Value), new Doeltank(
                               Convert.ToInt32(mengbatch.Attribute("Doeltank").Value)),
                               Convert.ToBoolean(mengbatch.Attribute("Klaar").Value),
                    Convert.ToInt32(mengbatch.Attribute("VerwarmTijd").Value)));

                    var vulbatchTables = mengbatch.Descendants("Vulbatch");
                    foreach (var vulbatch in vulbatchTables)
                    {
                        mengbatchListFromFile[mengbatchListFromFile.Count - 1].VulbatchList.Add(new Vulbatch(
                               Convert.ToInt32(vulbatch.Attribute("Nummer").Value),
                               Convert.ToInt32(vulbatch.Attribute("Mengbatch").Value),
                               Convert.ToInt32(vulbatch.Attribute("Aantalvaten").Value),
                               Convert.ToBoolean(vulbatch.Attribute("Klaar").Value)));
                        string apparaten = vulbatch.Attribute("Klaar").Value;
                        string[] splitter = apparaten.Split(' ');
                        for (int z = 0; z < splitter.Length - 1; z++)
                        {
                            mengbatchListFromFile[mengbatchListFromFile.Count - 1].VulbatchList[z].GebruikteApparaten.Add(splitter[z]);
                        }
                    }
                }
                foreach (Mengbatch mengbatch in order.MengbatchList)
                {
                    mengbatchListFromFile.Add(mengbatch);
                }
                reader.Close();
            }
            return mengbatchListFromFile;
        }

        public List<string> ReadTimer()
        {
            List<string> timerList = new List<string>();
            if (File.Exists(location + fileNameOEE))
            {
                XmlReader reader = XmlReader.Create(location + fileNameOEE);
                XDocument x = XDocument.Load(reader);
                var timers = x.Descendants("OEE_Overzicht");
                foreach (var timer in timers)
                {
                    timerList.Add(timer.Element("Total_Time").Value);
                    timerList.Add(timer.Element("Total_Active_Time").Value);
                }
                reader.Close();
            }
            return timerList;
        }

        #endregion Read

        #region Write

        public void WriteOEE(List<ItemInfo> infoList, Stopwatch totalTime, Stopwatch totalTimeActive)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.CloseOutput = true;
            while (FileInUse(location + fileNameOEE) == true)
            { }
            XmlWriter writer = XmlWriter.Create(location + fileNameOEE, settings);
            writer.WriteStartDocument();
            writer.WriteStartElement("OEE_Overzicht");
            writer.WriteElementString("Total_Time", totalTime.Elapsed.ToString());
            writer.WriteElementString("Total_Active_Time", totalTimeActive.Elapsed.ToString());
            writer.WriteStartElement("Outputs");
            foreach (ItemInfo item in infoList)
            {
                if (CheckStringForWrite(item) == true)
                {
                    writer.WriteStartElement(item.FilteredName);
                    writer.WriteAttributeString("TijdActief", item.Timer.Elapsed.Seconds.ToString());
                    writer.WriteAttributeString("Effectiviteit", item.BerekenEffectiviteit());
                    writer.WriteEndElement();
                }
            }

            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
        }

        public void WriteOrderList(string folderName, string filename, BindingList<Order> orderList)
        {
            // Deze kan zowel Historie als Orders schrijven aangezien beide documenten hetzelfde opgebouwd zijn.
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.CloseOutput = true;
            if (File.Exists(folderName + filename))
            {
                File.Delete(folderName + filename);
            }
            XmlWriter writer = XmlWriter.Create(folderName + filename, settings);
            writer.WriteStartDocument();
            writer.WriteStartElement("Orderlist");
            foreach (Order orderItem in orderList)
            {
                writer.WriteStartElement("Order");
                writer.WriteAttributeString("Nummer", orderItem.Nummer.ToString());
                writer.WriteAttributeString("Naam", orderItem.Naam);
                writer.WriteAttributeString("Klaar", orderItem.Klaar.ToString());

                foreach (Mengbatch mengbatchItem in orderItem.MengbatchList)
                {
                    writer.WriteStartElement("Mengbatch");

                    writer.WriteAttributeString("Nummer", mengbatchItem.Nummer.ToString());
                    writer.WriteAttributeString("Productcode", mengbatchItem.Productcode);
                    writer.WriteAttributeString("Smaak", mengbatchItem.Smaak.Naam);
                    writer.WriteAttributeString("HoeveelheidVaten", mengbatchItem.Hoeveelheid.ToString());
                    writer.WriteAttributeString("Siroop", mengbatchItem.SiroopPercentage.ToString());
                    writer.WriteAttributeString("Mengtijd", mengbatchItem.Mengtijd.ToString());
                    writer.WriteAttributeString("Verwarmen", mengbatchItem.Verwarmen.ToString());
                    writer.WriteAttributeString("VerwarmTijd", mengbatchItem.VerwarmTijd.ToString());
                    writer.WriteAttributeString("Handmatig", mengbatchItem.Handmatig.ToString());
                    writer.WriteAttributeString("Doeltank", mengbatchItem.Doeltank.Nummer.ToString());
                    writer.WriteAttributeString("Klaar", mengbatchItem.Klaar.ToString());

                    foreach (Vulbatch vulbatchItem in mengbatchItem.VulbatchList)
                    {
                        writer.WriteStartElement("Vulbatch");

                        writer.WriteAttributeString("Nummer", vulbatchItem.Nummer.ToString());
                        writer.WriteAttributeString("Mengbatch", vulbatchItem.MengbatchNummer.ToString());
                        writer.WriteAttributeString("Aantalvaten", vulbatchItem.AantalVaten.ToString());
                        writer.WriteAttributeString("Klaar", vulbatchItem.Klaar.ToString());
                        string apparaten = "";
                        foreach (string item in vulbatchItem.GebruikteApparaten)
                        {
                            apparaten += item + " ";
                        }
                        writer.WriteAttributeString("Apparaten", vulbatchItem.Klaar.ToString());
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
            writer.Flush();
            writer.Close();
        }

        #endregion Write

        private bool FileInUse(string path)
        {
            try
            {
                using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
                {
                    if (fs.CanWrite == true)
                    {
                    }
                }
                return false;
            }
            catch (IOException)
            {
                return true;
            }
        }
    }
}